function PDMaskData(width, height, data) {
    this.width = width;
    this.height = height;
    this.data = data;
}

function PDSoftMask() {
    this.m_BBox = [];
    this.m_mtMatrix = null;
    this.m_groupForm = null;
    this.m_bLuminosity = false;
    this.m_backColor = 0xff000000;
    this.m_bFuncTrans = false;
    this.m_func = null;
    this.m_TransData = [];//256 BYTE
    //this.m_maskData = null;//a UIntArray object for store 8bpp mask data;
    this.m_genState = null;
    this.ParseFromBin = function (rd) {
        this.m_mtMatrix = new PDMatrix();
        var tmp = [];
        for (var j = 0; j < 6; j++) {
            tmp[j] = rd.readFloat32();
        }
        for (var k = 0; k < 4; k++) {
            this.m_BBox[k] = rd.readFloat32();
        }
        this.m_mtMatrix.Set(tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5]);
        this.m_groupForm = new PDForm(this.m_genState.m_pdObjs.m_pdDoc, this.m_genState.m_pdObjs.m_csImgPath);
        this.m_groupForm.ParseFromBin(rd);

        this.m_bLuminosity = rd.readByte();
        this.m_backColor = rd.readUint32();
        this.m_bFuncTrans = rd.readByte();
        /*
        for (var i = 0; i < 256; i++) {
        this.m_TransData[i] = rd.readByte();
        }*/
        if (this.m_bFuncTrans == 1) {
            this.m_func = _LoadAFunc_InBin(rd);
        }

    }
    //return a UInt8Array object to store 8bpp mask data;
    this.GetMaskData = function (w, h, clipRect, mtObj2Dev) {

        var width = clipRect[2] - clipRect[0];
        var height = clipRect[3] - clipRect[1];

        var cnvs = document.createElement("canvas"); //document.getElementById('myCanvas'); //
        cnvs.width = width;
        cnvs.height = height;
        var ctx = cnvs.getContext("2d");


        var a = (this.m_backColor >> 24) & 0xFF;
        var r = (this.m_backColor >> 16) & 0xFF;
        var g = (this.m_backColor >> 8) & 0xFF;
        var b = (this.m_backColor) & 0xFF;
        var fillRGB = "RGBA(" + r + "," + g + "," + b + "," + a + ")";
      //  ctx.fillStyle = fillRGB;
      //  ctx.fillRect(0, 0, w, h);

        var l = clipRect[0] * (-1);
        var t = clipRect[1] * (-1);
        //   mtObj2Dev.Translate(l, t, false);
        var mtFinal = new PDMatrix();
        mtFinal.Clon(this.m_mtMatrix);
        mtFinal.Concat(mtObj2Dev.a, mtObj2Dev.b, mtObj2Dev.c, mtObj2Dev.d, mtObj2Dev.e, mtObj2Dev.f, false);
        mtFinal.Translate(l, t, false);


        var r = new PDRenderContext();
        r.globalUseAlphaWhenBitblt = false;
        r.bgClr = fillRGB;
        r.AppandObjList(this.m_groupForm.GetPageObjects(), mtFinal);
        r.Render(cnvs, null, null, 0);


        var final_img = ctx.getImageData(0, 0, width, height);

        //argb -> 8bpp mask;
        var bytes = new Uint8Array(width * height);
        for (var i = 0; i < final_img.data.length; i = i + 4) {
            bytes[i / 4] = (((final_img.data[i + 2]) * 11 + (final_img.data[i + 1]) * 59 + (final_img.data[i]) * 30) / 100);

        }
        delete cnvs;
        if (this.m_func != null) {
            for (var j = 0; j < 256; j++) {
                var input = []; // j / 255;
                input[0] = j / 255;
                var results = [];
                this.m_func.Call(input, 1, results);
                this.m_TransData[j] = Math.floor(results[0] * 255);
            }
        } else {
            for (var j = 0; j < 256; j++) {
                this.m_TransData[j] = j;
            }
        }

        if (this.m_bLuminosity) {
            for (var j = 0; j < bytes.length; j++) {
                bytes[j] = this.m_TransData[bytes[j]];
            }
        } else if (this.m_func) {
            for (var j = 0; j < bytes.length; j++) {
                bytes[j] = this.m_TransData[bytes[j]];
            }
        }
        var maskData = new PDMaskData(width, height, bytes);
        return maskData;

    }
}